/*
 * @Author: xuetao 3168581151@qq.com
 * @Date: 2025-02-22
 * @LastEditors: xuetao 3168581151@qq.com
 * @LastEditTime: 2025-04-16
 * @Description: 
 */
import 'dart:async';
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:typed_data';
import 'package:image_picker/image_picker.dart';

// Web端处理图片流程
Future<XFile?> processImage(bool enableFreeStyle) async {
  // 选取
  final pickedFile = await pickImage();
  if (pickedFile == null) return null;

  // 裁剪
  final croppedFile =
      await cropImage(pickedFile.path, pickedFile.name, enableFreeStyle);

  return croppedFile;
}

//  选择图片
Future<XFile?> pickImage() async {
  final input = html.FileUploadInputElement()
    ..accept = 'image/*'
    ..multiple = false;
  input.click();

  final completer = Completer<XFile?>();
  input.onChange.listen((event) async {
    final file = input.files?.first;
    if (file == null) {
      completer.complete(null);
      return;
    }

    final reader = html.FileReader();
    reader.readAsArrayBuffer(file);
    reader.onLoadEnd.listen((e) {
      final bytes = reader.result as Uint8List?;
      if (bytes != null) {
        final blob = html.Blob([bytes], file.type);
        final url = html.Url.createObjectUrlFromBlob(blob);
        completer.complete(XFile(url, name: file.name));
      }
    });
  });
  return completer.future;
}

// 裁剪图片
// 裁剪图片
Future<XFile?> cropImage(
    String imageUrl, String filename, bool enableFreeStyle) async {
  final completer = Completer<XFile?>();

  // 创建全屏遮罩层
  final modal = html.DivElement()
    ..style.cssText = '''
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      background: rgba(0, 0, 0, 0.8);
      z-index: 9999;
      display: flex;
      justify-content: center;
      align-items: center;
    ''';

  // 图片容器
  final container = html.DivElement()
    ..style.cssText = '''
      position: relative;
      width: 80%;
      height: 80%;
      background: white;
    ''';

  // 初始化图片元素
  final img = html.ImageElement()
    ..src = imageUrl
    ..style.objectFit = 'contain'
    ..style.width = '100%'
    ..style.height = '100%';

  // 动态构建 Cropper 配置
  final cropperOptions = {
    'aspectRatio': enableFreeStyle ? double.nan : 1, // 关键修改：自由模式设为 NaN
    'viewMode': enableFreeStyle ? 1 : 2, // 自由模式放宽视图限制
    'autoCropArea': 0.8,
    'dragMode': 'move', // 允许拖拽画布
    'movable': true, // 允许移动裁剪框
    'rotatable': enableFreeStyle, // 自由模式允许旋转
    'scalable': enableFreeStyle, // 自由模式允许缩放
    'zoomable': enableFreeStyle, // 自由模式允许缩放画布
    'toggleDragModeOnDblclick': enableFreeStyle, // 双击切换拖拽模式
  };

  // 初始化 Cropper
  final cropper = js.JsObject(
      js.context['Cropper'], [img, js.JsObject.jsify(cropperOptions)]);

  // 创建操作工具栏
  final toolbar = _buildToolbar(enableFreeStyle, cropper);

  // 界面组装
  container.append(img);
  modal.append(container);
  modal.append(toolbar);
  html.document.body!.append(modal);

  // 事件监听处理
  _setupEventListeners(cropper, modal, completer, filename);

  return completer.future;
}

// 构建工具栏组件
html.DivElement _buildToolbar(bool enableFreeStyle, js.JsObject cropper) {
  final toolbar = html.DivElement()
    ..style.cssText = '''
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      display: flex;
      gap: 10px;
      z-index: 10000;
    ''';

  // 确认按钮
  final confirmBtn = html.ButtonElement()
    ..text = '✓ 确认'
    ..style.cssText = '${_buttonStyle}background: #4CAF50;';

  // 取消按钮
  final cancelBtn = html.ButtonElement()
    ..text = '✕ 取消'
    ..style.cssText = '${_buttonStyle}background: #f44336;';

  // 自由模式专用按钮
  if (enableFreeStyle) {
    final rotateLeftBtn = html.ButtonElement()
      ..text = '↺ 左旋转'
      ..style.cssText = '${_buttonStyle}background: #409EFF;'
      ..onClick.listen((_) => _rotate(cropper, -45));

    final rotateRightBtn = html.ButtonElement()
      ..text = '↻ 右旋转'
      ..style.cssText = '${_buttonStyle}background: #409EFF;'
      ..onClick.listen((_) => _rotate(cropper, 45));

    final resetBtn = html.ButtonElement()
      ..text = '↻ 重置'
      ..style.cssText = '${_buttonStyle}background: #E6A23C;'
      ..onClick.listen((_) => cropper.callMethod('reset'));

    toolbar.children.addAll([rotateLeftBtn, rotateRightBtn, resetBtn]);
  }

  toolbar.children.addAll([confirmBtn, cancelBtn]);
  return toolbar;
}

// 按钮基础样式
const _buttonStyle = '''
  padding: 8px 16px;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: opacity 0.3s;
''';

// 旋转操作
void _rotate(js.JsObject cropper, num degree) {
  final currentRotate = cropper.callMethod('getData')['rotate'] ?? 0;
  cropper.callMethod('rotateTo', [currentRotate + degree]);
}

// 事件监听处理
void _setupEventListeners(js.JsObject cropper, html.DivElement modal,
    Completer<XFile?> completer, String filename) {
  StreamSubscription? sub;

  // 确认按钮处理
  sub = modal.querySelector('button')!.onClick.listen((event) async {
    if ((event.target as html.ButtonElement).text != '✓ 确认') return;

    final jsCropper = js.JsObject.fromBrowserObject(cropper);
    final canvas = jsCropper.callMethod('getCroppedCanvas');

    if (canvas != null) {
      final blob = await canvas.toBlob('image/jpeg', 0.9);
      final url = html.Url.createObjectUrlFromBlob(blob);
      completer.complete(XFile(url, name: 'cropped_$filename'));
    }

    _cleanupResources(cropper, modal, sub);
  });

  // 取消按钮处理
  modal.querySelectorAll('button').forEach((btn) {
    if (btn.text == '✕ 取消') {
      btn.onClick.listen((_) {
        _cleanupResources(cropper, modal, sub);
        completer.complete(null);
      });
    }
  });
}

// 清理资源
void _cleanupResources(
    js.JsObject cropper, html.DivElement modal, StreamSubscription? sub) {
  modal.remove();
  cropper.callMethod('destroy');
  sub?.cancel();
}

// 上传完成后，文件内存释放
Future<void> cleanTempFiles(XFile? file) async {
  if (file == null) return;
  // Web 端：释放 Blob URL
  html.Url.revokeObjectUrl(file.path);
  return;
}
